home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.10 Oct 94 / Programmers' Challenge / DumpBytes.c
Encoding:
C/C++ Source or Header  |  1994-09-13  |  6.7 KB  |  272 lines  |  [TEXT/KAHL]

  1. /* Dump Bytes.
  2.  * Dave Darrah, Lansdale, PA          
  3.  */
  4.  
  5. #include <string.h>
  6.  
  7. typedef unsigned short *  usp;
  8.  
  9. // For unknown reasons, Think generates more efficient code 
  10. //  for the critical  *(usp)outputText = aTablePtr[byte]
  11. //  instructions when register coloring is off. Go figure.
  12.  
  13. #pragma options (honor_register,\
  14.                 !assign_registers,\
  15.                 !gopt_coloring)
  16.  
  17. // Address registers are used for:
  18. //       the "inputBytes" pointer, passed parameter.
  19. //       the "outputText" pointer, passed parameter.
  20. //       the "outputTextA" pointer, which points to where 
  21. //                        the    Ascii representation goes.
  22.  
  23. // Data registers are used for:
  24. //       "space", a holder of a space.
  25. //       "byte", a temp area that holds a value we want to
  26. //                 "burst" to ascii.
  27. //       "eCntr, gCntr", counters used for two loops.
  28. //       Pointer to "aTable": "aTablePtr". Think assigns the
  29. //                 last data reg to it.
  30.  
  31. unsigned short      DumpBytes(inputBytes, 
  32.                                  outputText,
  33.                                  numInputBytes, 
  34.                                  maxOutputBytes,
  35.                                  width,
  36.                                  grouping)
  37.           
  38.   register    Ptr                inputBytes;
  39.   register    Ptr                outputText;
  40.               unsigned short  numInputBytes;
  41.               unsigned short  maxOutputBytes;
  42.               unsigned short  width;
  43.               unsigned short  grouping;
  44. {
  45.  
  46.   register  Byte            space=' ';
  47.   register     Byte                byte;
  48.   register     unsigned short     eCntr,gCntr;
  49.  
  50.   register     Ptr                  outputTextA;
  51.   
  52.                unsigned short     dispValue=0;   
  53.     // This is the hex value of what's printed at the
  54.     //       beginning of each line.
  55.  
  56.                unsigned short     groupsPerLine,lineLength,extras,
  57.                                numberOfLines,asciiOffset,
  58.                                lastLineLength;
  59.                                
  60.                Boolean            truncated=FALSE;
  61.               Ptr                saveOutputText=outputText;
  62.  
  63. // 256 entry (512 byte) ascii table. This table will be 
  64. //  indexed by the byte value, to return the two-char entry
  65. //  that is the character representation of that byte. See
  66. //  note later about how Think generates this table.
  67.  
  68.   static    char            aTable[] = "\
  69. 000102030405060708090A0B0C0D0E0F\
  70. 101112131415161718191A1B1C1D1E1F\
  71. 202122232425262728292A2B2C2D2E2F\
  72. 303132333435363738393A3B3C3D3E3F\
  73. 404142434445464748494A4B4C4D4E4F\
  74. 505152535455565758595A5B5C5D5E5F\
  75. 606162636465666768696A6B6C6D6E6F\
  76. 707172737475767778797A7B7C7D7E7F\
  77. 808182838485868788898A8B8C8D8E8F\
  78. 909192939495969798999A9B9C9D9E9F\
  79. A0A1A2A3A4A5A6A7A8A9AAABACADAEAF\
  80. B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF\
  81. C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF\
  82. D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF\
  83. E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF\
  84. F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF";
  85.  
  86.   register usp aTablePtr=(usp)&aTable; 
  87.     // Think gives aTablePtr a data register, 
  88.     //  and it actually helps!
  89.  
  90. /*********************************************************/
  91.   
  92.  
  93.  
  94. /**********************************************************/
  95.   
  96.   // That's it for local variables, first, let's initialize 
  97.   //   a few variables and preflight the output length.
  98.   
  99.    // Because of some flukie I haven't been able to scope
  100.    //  out (a possible Think bug?), the last value (the
  101.    //  right "F" in "FF") of aTable is hex 0. Why? Don't
  102.    //  know. Oh well, let's just roll with the punch.
  103.    
  104.     aTable[511] = 'F';
  105.    
  106.  
  107.    // Calculate number of groups per line.
  108.    
  109.     groupsPerLine = width/grouping;
  110.     
  111.     
  112.    // Calculate output line length.
  113.  
  114.     lineLength = width*3 + groupsPerLine + 7;       
  115.              // 2 for hex representation, 1 for ascii;
  116.              // 1 for each space that follows a group;
  117.              // 4 for disp, a colon, space and return.
  118.  
  119.  
  120.    // Calculate offset from outputText where ascii goes.
  121.    
  122.     asciiOffset = lineLength - width - 1;
  123.  
  124.    
  125.    // Calculate the number of full lines of output.
  126.  
  127.     numberOfLines = numInputBytes/width;
  128.  
  129.  
  130.    // Calculate the number of bytes left over after all 
  131.    //  complete lines are done.
  132.    
  133.     extras = numInputBytes % width;
  134.     
  135.  
  136.    // Calculate the number of bytes this line takes.
  137.        
  138.     lastLineLength = asciiOffset + extras;
  139.  
  140.  
  141.    // Reduce numberOfLines if output would run past 
  142.    //  maxOutputBytes. Just dump the number of full
  143.    //  lines that fit in maxOutputBytes.
  144.     
  145.     if ( (lineLength * (unsigned long)numberOfLines) +
  146.             lastLineLength  > maxOutputBytes)  {
  147.         numberOfLines = maxOutputBytes/lineLength;
  148.         extras = 0;
  149.         truncated = TRUE;
  150.     }
  151.  
  152.  
  153.  
  154.   /*******************************************************/
  155.  
  156.    // Initialization and preflighting done. 
  157.    // It's time to process the input.
  158.  
  159.     numberOfLines++;
  160.     while (--numberOfLines)  {    // Do each full line.
  161.  
  162.         outputTextA = outputText+asciiOffset;
  163.     
  164.           // Displacement value goes first.         
  165.         byte = dispValue>>8; // left byte of disp
  166.     
  167.         *(usp)outputText = aTablePtr[byte];
  168.         outputText += 2;
  169.  
  170.         byte = dispValue;  // right byte of disp
  171.     
  172.         *(usp)outputText = aTablePtr[byte];
  173.         outputText += 2;
  174.  
  175.         *(usp)outputText = ': ';
  176.         outputText += 2;
  177.     
  178.         dispValue += width;
  179.     
  180.        // Now do "groupsPerLine" sets of hex expansions.
  181.         eCntr = groupsPerLine;
  182.         do {       // each of the "groupsPerLine" groups.
  183.     
  184.             gCntr = grouping;
  185.             do {   // each of the "grouping" bytes.
  186.         
  187.                 byte = *inputBytes++;
  188.                 *(usp)outputText = aTablePtr[byte];
  189.                  outputText += 2;
  190.  
  191.                // Do the ascii.
  192.                 if (byte < space || byte > 0x7E)
  193.                     *outputTextA++ = '.';
  194.                 else
  195.                     *outputTextA++ = byte;
  196.                     
  197.             } while (--gCntr); // End "grouping bytes" loop
  198.  
  199.             *outputText++ = space;  // Space after each group
  200.         
  201.         }    while (--eCntr);   // End "groups per line" loop
  202.     
  203.         *outputTextA++ = '\r';
  204.     
  205.        // Point to beginning of next line.
  206.         outputText = outputTextA;
  207.     
  208.     }        // End of "lines" loop.
  209.  
  210.  
  211.  
  212.    //  Now to worry, if necessary, about dribble left over.
  213.    //   A lot of code duplication, but what the hey!
  214.  
  215.     if ( extras )  {
  216.        // Space output line.
  217.         memset(outputText,space,lineLength);
  218.  
  219.         outputTextA = outputText+asciiOffset;
  220.     
  221.           // Displacement value goes first.         
  222.         byte = dispValue>>8; // left byte of disp
  223.     
  224.         *(usp)outputText = aTablePtr[byte];
  225.         outputText += 2;
  226.  
  227.         byte = dispValue;     // right byte of disp
  228.     
  229.         *(usp)outputText = aTablePtr[byte];
  230.         outputText += 2;
  231.  
  232.         *outputText = ':'; // space is already there.
  233.         outputText += 2;
  234.     
  235.        // Now do "groupsPerLine" sets of hex expansions.
  236.         eCntr = groupsPerLine;
  237.         do {    //  each of the "groupsPerLine" groups.
  238.     
  239.             gCntr = grouping;
  240.             do {   // each of the "grouping" bytes.
  241.         
  242.                 byte = *inputBytes++;
  243.                 *(usp)outputText = aTablePtr[byte];
  244.                  outputText += 2;
  245.  
  246.                // Do the ascii.
  247.                 if (byte < space || byte > 0x7E)
  248.                     *outputTextA++ = '.';
  249.                 else
  250.                     *outputTextA++ = byte;
  251.                 
  252.                 if (!--extras)
  253.                     goto AllDone; // Nasty termination when
  254.                                   //   we've done 'em all.
  255.                 
  256.             } while (--gCntr); // End "bytes in group" loop
  257.  
  258.            // skip past space after each group.
  259.             *outputText++;
  260.         
  261.         }    while (--eCntr); // End of groups per line loop.
  262.         
  263.     }  // end if
  264.  
  265.    AllDone:
  266.  
  267.     if (truncated)
  268.         return 0;
  269.     else
  270.         return(outputTextA - saveOutputText);
  271. }
  272.